{-# LANGUAGE CPP #-}
{-# LANGUAGE NoMonoLocalBinds #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ViewPatterns #-}
-- |
-- Module      : Streamly.Internal.Data.Parser.ParserD.Type
-- Copyright   : (c) 2020 Composewell Technologies
-- License     : BSD-3-Clause
-- Maintainer  : streamly@composewell.com
-- Stability   : experimental
-- Portability : GHC
--
-- Streaming and backtracking parsers.
--
-- Parsers just extend folds.  Please read the 'Fold' design notes in
-- "Streamly.Internal.Data.Fold.Type" for background on the design.
--
-- = Parser Design
--
-- The 'Parser' type or a parsing fold is a generalization of the 'Fold' type.
-- The 'Fold' type /always/ succeeds on each input. Therefore, it does not need
-- to buffer the input. In contrast, a 'Parser' may fail and backtrack to
-- replay the input again to explore another branch of the parser. Therefore,
-- it needs to buffer the input. Therefore, a 'Parser' is a fold with some
-- additional requirements.  To summarize, unlike a 'Fold', a 'Parser':
--
-- 1. may not generate a new value of the accumulator on every input, it may
-- generate a new accumulator only after consuming multiple input elements
-- (e.g. takeEQ).
-- 2. on success may return some unconsumed input (e.g. takeWhile)
-- 3. may fail and return all input without consuming it (e.g. satisfy)
-- 4. backtrack and start inspecting the past input again (e.g. alt)
--
-- These use cases require buffering and replaying of input.  To facilitate
-- this, the step function of the 'Fold' is augmented to return the next state
-- of the fold along with a command tag using a 'Step' functor, the tag tells
-- the fold driver to manipulate the future input as the parser wishes. The
-- 'Step' functor provides the following commands to the fold driver
-- corresponding to the use cases outlined in the previous para:
--
-- 1. 'Continue': buffer the current input and optionally go back to a previous
--    position in the stream
-- 2. 'Partial': buffer the current input and optionally go back to a previous
--    position in the stream, drop the buffer before that position.
-- 3. 'Done': parser succeeded, returns how much input was leftover
-- 4. 'SError': indicates that the parser has failed without a result
--
-- = How a Parser Works?
--
-- A parser is just like a fold, it keeps consuming inputs from the stream and
-- accumulating them in an accumulator. The accumulator of the parser could be
-- a singleton value or it could be a collection of values e.g. a list.
--
-- The parser may build a new output value from multiple input items. When it
-- consumes an input item but needs more input to build a complete output item
-- it uses @Continue 0 s@, yielding the intermediate state @s@ and asking the
-- driver to provide more input.  When the parser determines that a new output
-- value is complete it can use a @Done n b@ to terminate the parser with @n@
-- items of input unused and the final value of the accumulator returned as
-- @b@. If at any time the parser determines that the parse has failed it can
-- return @SError err@.
--
-- A parser building a collection of values (e.g. a list) can use the @Partial@
-- constructor whenever a new item in the output collection is generated. If a
-- parser building a collection of values has yielded at least one value then
-- it is considered successful and cannot fail after that. In the current
-- implementation, this is not automatically enforced, there is a rule that the
-- parser MUST use only @Done@ for termination after the first @Partial@, it
-- cannot use @SError@. It may be possible to change the implementation so that
-- this rule is not required, but there may be some performance cost to it.
--
-- 'Streamly.Internal.Data.Parser.takeWhile' and
-- 'Streamly.Internal.Data.Parser.some' combinators are good examples of
-- efficient implementations using all features of this representation.  It is
-- possible to idiomatically build a collection of parsed items using a
-- singleton parser and @Alternative@ instance instead of using a
-- multi-yield parser.  However, this implementation is amenable to stream
-- fusion and can therefore be much faster.
--
-- = SError Handling
--
-- When a parser's @step@ function is invoked it may terminate by either a
-- 'Done' or an 'SError' return value. In an 'Alternative' composition an error
-- return can make the composed parser backtrack and try another parser.
--
-- If the stream stops before a parser could terminate then we use the
-- @extract@ function of the parser to retrieve the last yielded value of the
-- parser. If the parser has yielded at least one value then @extract@ MUST
-- return a value without throwing an error, otherwise it uses the 'ParseError'
-- exception to throw an error.
--
-- We chose the exception throwing mechanism for @extract@ instead of using an
-- explicit error return via an 'Either' type for keeping the interface simple
-- as most of the time we do not need to catch the error in intermediate
-- layers. Note that we cannot use exception throwing mechanism in @step@
-- function because of performance reasons. 'SError' constructor in that case
-- allows loop fusion and better performance.
--
-- = Optimizing backtracking
--
-- == Applicative Composition
--
-- If a parser once returned 'Partial' it can never fail after that. This is
-- used to reduce the buffering. A 'Partial' results in dropping the buffer and
-- we cannot backtrack before that point.
--
-- Parsers can be composed using an Alternative, if we are in an alternative
-- composition we may have to backtrack to try the other branch.  When we
-- compose two parsers using applicative @f <$> p1 <*> p2@ we can return a
-- 'Partial' result only after both the parsers have succeeded. While running
-- @p1@ we have to ensure that the input is not dropped until we have run @p2@,
-- therefore we have to return a Continue instead of a Partial.
--
-- However, if we know they both cannot fail then we know that the composed
-- parser can never fail.  For this reason we should have "backtracking folds"
-- as a separate type so that we can compose them in an efficient manner. In p1
-- itself we can drop the buffer as soon as a 'Partial' result arrives. In
-- fact, there is no Alternative composition for folds because they cannot
-- fail.
--
-- == Alternative Composition
--
-- In @p1 <|> p2@ as soon as the parser p1 returns 'Partial' we know that it
-- will not fail and we can immediately drop the buffer.
--
-- If we are not using the parser in an alternative composition we can
-- downgrade the parser to a backtracking fold and use the "backtracking
-- fold"'s applicative for more efficient implementation. To downgrade we can
-- translate the "SError" of parser to an exception.  This gives us best of both
-- worlds, the applicative as well as alternative would have optimal
-- backtracking buffer.
--
-- The "many" for parsers would be different than "many" for folds. In case of
-- folds an error would be propagated. In case of parsers the error would be
-- ignored.
--
-- = Implementation Approach
--
-- Backtracking folds have an issue with tee style composition because each
-- fold can backtrack independently, we will need independent buffers. Though
-- this may be possible to implement it may not be efficient especially for
-- folds that do not backtrack at all. Three types are possible, optimized for
-- different use cases:
--
-- * Non-backtracking folds: efficient Tee
-- * Backtracking folds: efficient applicative
-- * Parsers: alternative
--
-- Downgrade parsers to backtracking folds for applicative used without
-- alternative.  Upgrade backtracking folds to parsers when we have to use them
-- as the last alternative.
--
-- = Future Work
--
-- It may make sense to move "takeWhile" type of parsers, which cannot fail but
-- need some lookahead, to splitting folds.  This will allow such combinators
-- to be accepted where we need an unfailing "Fold" type.
--
-- Based on application requirements it should be possible to design even a
-- richer interface to manipulate the input stream/buffer. For example, we
-- could randomly seek into the stream in the forward or reverse directions or
-- we can even seek to the end or from the end or seek from the beginning.
--
-- We can distribute and scan/parse a stream using both folds and parsers and
-- merge the resulting streams using different merge strategies (e.g.
-- interleaving or serial).
--
-- == Naming
--
-- As far as possible, try that the names of the combinators in this module are
-- consistent with:
--
-- * <https://hackage.haskell.org/package/base/docs/Text-ParserCombinators-ReadP.html base/Text.ParserCombinators.ReadP>
-- * <http://hackage.haskell.org/package/parser-combinators parser-combinators>
-- * <http://hackage.haskell.org/package/megaparsec megaparsec>
-- * <http://hackage.haskell.org/package/attoparsec attoparsec>
-- * <http://hackage.haskell.org/package/parsec parsec>

module Streamly.Internal.Data.Parser.Type
    (
    -- * Types
      Initial (..)
    -- (..) does not seem to export patterns yet the compiler complains it does.
    , Step(Partial, Continue, Done, Error, SPartial, SContinue, SDone, SError)
    , Final(..)
    , mapCount
    , bimapOverrideCount
    , bimapMorphOverrideCount
    , Parser (..)
    , ParseError (..)
    , ParseErrorPos (..)
    , rmapM

    -- * Constructors

    , fromPure
    , fromEffect
    , splitWith
    , split_

    , die
    , dieM
    , splitSome -- parseSome?
    , splitMany -- parseMany?
    , splitManyPost
    , alt
    , concatMap

    -- * Input transformation
    , lmap
    , lmapM
    , filter

    , noErrorUnsafeSplitWith
    , noErrorUnsafeSplit_
    , noErrorUnsafeConcatMap

    , localReaderT
    )
where

#include "inline.hs"
#include "assert.hs"

#if !MIN_VERSION_base(4,18,0)
import Control.Applicative (liftA2)
#endif
import Control.Applicative (Alternative(..))
import Control.Exception (Exception(..))
-- import Control.Monad (MonadPlus(..), (>=>))
import Control.Monad ((>=>))
import Control.Monad.IO.Class (MonadIO, liftIO)
import Control.Monad.Trans.Reader (ReaderT, local)
import Data.Bifunctor (Bifunctor(..))
import Fusion.Plugin.Types (Fuse(..))
import Streamly.Internal.Data.Fold.Type (Fold(..), toList)

import qualified Control.Monad.Fail as Fail
import qualified Streamly.Internal.Data.Fold.Type as FL

import Prelude hiding (concatMap, filter)

#include "DocTestDataParser.hs"

-- XXX The only differences between Initial and Step types are:
--
-- * There are no backtracking counts in Initial
-- * Continue and Partial are the same. Ideally Partial should mean that an
-- empty result is valid and can be extracted; and Continue should mean that
-- empty would result in an error on extraction. We can possibly distinguish
-- the two cases.
--
-- If we ignore the backtracking counts we can represent the Initial type using
-- Step itself. That will also simplify the implementation of various parsers
-- where the processing in intiial is just a sepcial case of step, see
-- takeBetween for example.

-- XXX IPartial indicates that the parser has a default result and cannot fail.
-- Such parsers should rather be written as Parslets? We should use IContinue
-- in initial.

-- | The type of a 'Parser''s initial action.
--
-- /Internal/
--
{-# ANN type Initial Fuse #-}
data Initial s b
    = IPartial !s   -- ^ Wait for step function to be called with state @s@.
    | IDone !b      -- ^ Return a result right away without an input.
    | IError !String -- ^ Return an error right away without an input.

-- | @first@ maps on 'IPartial' and @second@ maps on 'IDone'.
--
-- /Internal/
--
instance Bifunctor Initial where
    {-# INLINE bimap #-}
    bimap f _ (IPartial a) = IPartial (f a)
    bimap _ g (IDone b) = IDone (g b)
    bimap _ _ (IError err) = IError err

-- | Maps a function over the result held by 'IDone'.
--
-- >>> fmap = second
--
-- /Internal/
--
instance Functor (Initial s) where
    {-# INLINE fmap #-}
    fmap = second

-- We can simplify the Step type as follows:
--
-- Partial Int (Either s (s, b)) -- Left continue, right partial result
-- Done Int (Either String b)
--
-- In this case SError may also have a "leftover" return. This means that after
-- several successful partial results the last segment parsing failed and we
-- are returning the leftover of that. The driver may choose to restart from
-- the last segment where this parser failed or from the beginning.
--
-- Folds can only return the right values. Parsers can also return lefts.

-- | The return type of a 'Parser' step.
--
-- /Result types/: The parser driver feeds the input stream to the parser one
-- element at a time, representing a parse 'Step'. If the step result
-- 'SPartial' indicates that a parse result is available and the parser can
-- accept more input, we can extract the result using the parser's extract
-- function and feed more input to the parser. If the result is 'SContinue', we
-- must feed more input in order to get a result. If the parser returns 'SDone'
-- then a result is available and the parser can no longer take any more input.
--
-- /Stream position/: The @n@ in @SPartial n@, @Scontinue n@ and @SDone n@ is a
-- count by which we adjust the current stream position after this step. If the
-- count is positive we move forward in the stream, if it is 0 then we stay
-- where we are, if it is negative then we move backward in the stream.
-- Essentially, if the input stream position was @pos@ before processing the
-- current element then the new stream position after processing the element
-- would be @pos + n@.
--
-- We can also think of this count as the number of items consumed by the
-- parser. If the current input item is consumed then n is 1, if the current
-- input item should be presented to the next parser step then n is 0. If @n@
-- is less than 0 then the parser backtracks by n elements before the current
-- element before the next parsing step is invoked. @n@ is not allowed to be
-- greater than 1 in the regular stream parsers, but it can be more than 1 in
-- an array parser because it can consume more than one elements from the
-- array.
--
-- /Backtracking/: If the parser result is 'SContinue', the parser driver
-- retains the input in a backtracking buffer, in case of failure the parser
-- can backtrack maximum up to the length of the backtracking buffer. Whenever
-- the result is `SPartial` the current backtracking buffer is discarded; this
-- means that we cannot backtrack beyond the currrent position in the stream.
-- The parser must ensure that the backtrack position is always within the
-- bounds of the backtracking buffer, otherwise a runtime error will occur.
--
-- /Failure/: If the parser is not yet done, we can use the @extract@ operation
-- on the @state@ of the parser to extract a result. If the parser never
-- yielded a result in the past, @extract@ fails with a 'ParseError' exception.
-- If the parser yielded a 'Partial' result in the past then extract returns
-- the latest partial result. Therefore, if a parser yields a partial result
-- once then it cannot fail later on.
--
-- /Pre-release/
--
{-# ANN type Step Fuse #-}
data Step s b =
        SPartial !Int !s
    -- ^ @SPartial count state@. The following statements hold on an SPartial
    -- result:
    --
    -- 1. @extract@ on @state@ would succeed and give a result.
    -- 2. Input stream position is updated to @current position + count@.
    -- 3. All buffered input before the new position is dropped. The parser can
    -- never backtrack before this position.

    | SContinue !Int !s
    -- ^ @SContinue count state@. The following statements hold on an SContinue
    -- result:
    --
    -- 1. If 'SPartial' result was returned in the past, @extract@ on @state@
    -- would give that result otherwise it will return 'SError' or 'SContinue'.
    -- 2. Input stream position is updated to @current position + count@.
    -- 3. the previous input is retained in a backtrack buffer.

    | SDone !Int !b
    -- ^ Done with leftover input count and result.
    --
    -- @SDone count result@ means the parser has finished, it will not accept
    -- any more input, the final stream position must be set to @current
    -- position + count@ and the result of the parser is in @result@.

    | SError !String
    -- ^ Parser failed without generating any output.
    --
    -- The parsing operation may backtrack to the beginning and try another
    -- alternative.
    deriving (Show)

{-# ANN type Final Fuse #-}
data Final s b
    = FDone !Int !b      -- ^ Return a result right away without an input.
    | FContinue !Int !s
    | FError !String -- ^ Return an error right away without an input.

--------------------------------------------------------------------------------
-- Custom Patterns
--------------------------------------------------------------------------------

negateDirection :: Step s b -> Step s b
negateDirection (SPartial i s) = SPartial (1 - i) s
negateDirection (SContinue i s) = SContinue (1 - i) s
negateDirection (SDone i b) = SDone (1 - i) b
negateDirection (SError s) = SError s

{-# DEPRECATED Error "Use @SError@ instead of @Error@" #-}
pattern Error :: String -> Step s b
pattern Error s = SError s

{-# DEPRECATED Partial "Use @SPartial (1 - n)@ instead of @Partial n@" #-}
pattern Partial :: Int -> s -> Step s b
pattern Partial i s <- (negateDirection -> SPartial i s)
    where Partial i s = SPartial (1 - i) s

{-# DEPRECATED Continue "Replace @Continue n@ with @SContinue (1 - n)@ in parser step and with @FContinue (-n)@ in parser extract" #-}
pattern Continue :: Int -> s -> Step s b
pattern Continue i s <- (negateDirection -> SContinue i s)
    where Continue i s = SContinue (1 - i) s

{-# DEPRECATED Done "Replace @Done n@ with @SDone (1 - n)@ in parser step and with @FDone (-n)@ in parser extract" #-}
pattern Done :: Int -> b -> Step s b
pattern Done i b <- (negateDirection -> SDone i b)
    where Done i b = SDone (1 - i) b

--------------------------------------------------------------------------------
-- Code
--------------------------------------------------------------------------------

-- | Map first function over the state and second over the result.
instance Bifunctor Step where
    {-# INLINE bimap #-}
    bimap f g step =
        case step of
            SPartial n s -> SPartial n (f s)
            SContinue n s -> SContinue n (f s)
            SDone n b -> SDone n (g b)
            SError err -> SError err

instance Bifunctor Final where
    {-# INLINE bimap #-}
    bimap f g step =
        case step of
            FContinue n s -> FContinue n (f s)
            FDone n b -> FDone n (g b)
            FError err -> FError err

-- | Bimap discarding the count, and using the supplied count instead.
bimapOverrideCount :: Int -> (s -> s1) -> (b -> b1) -> Step s b -> Step s1 b1
bimapOverrideCount n f g step =
    case step of
        SPartial _ s -> SPartial n (f s)
        SContinue _ s -> SContinue n (f s)
        SDone _ b -> SDone n (g b)
        SError err -> SError err

bimapMorphOverrideCount :: Int -> (s -> s1) -> (b -> b1) -> Final s b -> Step s1 b1
bimapMorphOverrideCount n f g step =
    case step of
        FDone _ b -> SDone n (g b)
        FContinue _ s -> SContinue n (f s)
        FError err -> SError err

bimapFinalOverrideCount :: Int -> (s -> s1) -> (b -> b1) -> Final s b -> Final s1 b1
bimapFinalOverrideCount n f g step =
    case step of
        FContinue _ s -> FContinue n (f s)
        FDone _ b -> FDone n (g b)
        FError err -> FError err

-- | fmap = second
instance Functor (Step s) where
    {-# INLINE fmap #-}
    fmap = second

instance Functor (Final s) where
    {-# INLINE fmap #-}
    fmap = second

-- | Map a function over the count.
--
{-# INLINE mapCount #-}
mapCount :: (Int -> Int) -> Step s b -> Step s b
mapCount f res =
    case res of
        SPartial n s -> SPartial (f n) s
        SDone n b -> SDone (f n) b
        SContinue n s -> SContinue (f n) s
        SError err -> SError err

-- | Map a monadic function over the result @b@ in @Step s b@.
--
-- /Internal/
{-# INLINE mapMStep #-}
mapMStep :: Applicative m => (a -> m b) -> Step s a -> m (Step s b)
mapMStep f res =
    case res of
        SPartial n s -> pure $ SPartial n s
        SDone n b -> SDone n <$> f b
        SContinue n s -> pure $ SContinue n s
        SError err -> pure $ SError err

{-# INLINE mapMFinal #-}
mapMFinal :: Applicative m => (a -> m b) -> Final s a -> m (Final s b)
mapMFinal f res =
    case res of
        FDone n b -> FDone n <$> f b
        FContinue n s -> pure $ FContinue n s
        FError err -> pure $ FError err

-- | A parser is a fold that can fail and is represented as @Parser step
-- initial extract@. Before we drive a parser we call the @initial@ action to
-- retrieve the initial state of the fold. The parser driver invokes @step@
-- with the state returned by the previous step and the next input element. It
-- results into a new state and a command to the driver represented by 'Step'
-- type. The driver keeps invoking the step function until it stops or fails.
-- At any point of time the driver can call @extract@ to inspect the result of
-- the fold. If the parser hits the end of input 'extract' is called.
-- It may result in an error or an output value.
--
-- /Pre-release/
--
data Parser a m b =
    forall s. Parser
        (s -> a -> m (Step s b))
        (m (Initial s b))
        (s -> m (Final s b))

-- | This exception is used when a parser ultimately fails, the user of the
-- parser is intimated via this exception.
--
newtype ParseError = ParseError String
    deriving (Eq, Show)

instance Exception ParseError where
    displayException (ParseError err) = err

-- | Like 'ParseError' but reports the stream position where the error ocurred.
-- The @Int@ is the position in the stream where the error ocurred. This
-- exception is used by position reporting parser drivers.
data ParseErrorPos = ParseErrorPos Int String
    deriving (Eq, Show)

instance Exception ParseErrorPos where
    displayException (ParseErrorPos pos err) =
        concat ["At ", show pos, ":", err]

-- | Map a function on the result i.e. on @b@ in @Parser a m b@.
instance Functor m => Functor (Parser a m) where
    {-# INLINE fmap #-}
    fmap f (Parser step1 initial1 extract) =
        Parser step initial (fmap3 f extract)

        where

        initial = fmap2 f initial1
        step s b = fmap2 f (step1 s b)
        fmap2 g = fmap (fmap g)
        fmap3 g = fmap (fmap (fmap g))

------------------------------------------------------------------------------
-- Mapping on the output
------------------------------------------------------------------------------

-- | @rmapM f parser@ maps the monadic function @f@ on the output of the parser.
--
-- >>> rmap = fmap
{-# INLINE rmapM #-}
rmapM :: Monad m => (b -> m c) -> Parser a m b -> Parser a m c
rmapM f (Parser step initial extract) =
    Parser step1 initial1 (extract >=> mapMFinal f)

    where

    initial1 = do
        res <- initial
        -- this is mapM f over result
        case res of
            IPartial x -> return $ IPartial x
            IDone a -> IDone <$> f a
            IError err -> return $ IError err
    step1 s a = step s a >>= mapMStep f

-- | A parser that always yields a pure value without consuming any input.
--
{-# INLINE_NORMAL fromPure #-}
fromPure :: Monad m => b -> Parser a m b
fromPure b = Parser undefined (pure $ IDone b) undefined

-- | A parser that always yields the result of an effectful action without
-- consuming any input.
--
{-# INLINE fromEffect #-}
fromEffect :: Monad m => m b -> Parser a m b
fromEffect b = Parser undefined (IDone <$> b) undefined

-------------------------------------------------------------------------------
-- Sequential applicative
-------------------------------------------------------------------------------

{-# ANN type SeqParseState Fuse #-}
data SeqParseState sl f sr = SeqParseL !sl | SeqParseR !f !sr

-- Note: this implementation of splitWith is fast because of stream fusion but
-- has quadratic time complexity, because each composition adds a new branch
-- that each subsequent parse's input element has to go through, therefore, it
-- cannot scale to a large number of compositions. After around 100
-- compositions the performance starts dipping rapidly beyond a CPS style
-- unfused implementation.
--
-- Note: This is a parsing dual of appending streams using
-- 'Streamly.Data.Stream.append', it splits the streams using two parsers and
-- zips the results.

-- | Sequential parser application. Apply two parsers sequentially to an input
-- stream. The first parser runs and processes the input, the remaining input
-- is then passed to the second parser. If both parsers succeed, their outputs
-- are combined using the supplied function. If either parser fails, the
-- operation fails.
--
-- This combinator delivers high performance by stream fusion but it comes with
-- some limitations. For those cases use the 'Applicative' instance of
-- 'Streamly.Data.ParserK.ParserK'.
--
-- CAVEAT 1: NO RECURSION. This function is strict in both arguments. As a
-- result, if a parser is defined recursively using this, it may cause an
-- infintie loop. The following example checks the strictness:
--
-- >>> p = Parser.splitWith const (Parser.satisfy (> 0)) undefined
-- >>> Stream.parse p $ Stream.fromList [1]
-- *** Exception: Prelude.undefined
-- ...
--
-- CAVEAT 2: QUADRATIC TIME COMPLEXITY. Static composition is fast due to
-- stream fusion, but it works well only for limited (e.g. up to 8)
-- compositions, use "Streamly.Data.ParserK" for larger compositions.
--
-- Below are some common idioms that can be expressed using 'splitWith':
--
-- >>> span p f1 f2 = Parser.splitWith (,) (Parser.takeWhile p f1) (Parser.fromFold f2)
-- >>> spanBy eq f1 f2 = Parser.splitWith (,) (Parser.groupBy eq f1) (Parser.fromFold f2)
--
-- /Pre-release/
--
{-# INLINE splitWith #-}
splitWith :: Monad m
    => (a -> b -> c) -> Parser x m a -> Parser x m b -> Parser x m c
splitWith func (Parser stepL initialL extractL)
               (Parser stepR initialR extractR) =
    Parser step initial extract

    where

    initial = do
        -- XXX We can use bimap here if we make this a Step type
        resL <- initialL
        case resL of
            IPartial sl -> return $ IPartial $ SeqParseL sl
            IDone bl -> do
                resR <- initialR
                -- XXX We can use bimap here if we make this a Step type
                return $ case resR of
                    IPartial sr -> IPartial $ SeqParseR (func bl) sr
                    IDone br -> IDone (func bl br)
                    IError err -> IError err
            IError err -> return $ IError err

    -- Note: For the composed parse to terminate, the left parser has to be
    -- a terminating parser returning a Done at some point.
    step (SeqParseL st) a = do
        -- Important: Please do not use Applicative here. See
        -- https://github.com/composewell/streamly/issues/1033 and the problem
        -- defined in split_ for more info.
        -- XXX Use bimap
        resL <- stepL st a
        case resL of
            -- Note: We need to buffer the input for a possible Alternative
            -- e.g. in ((,) <$> p1 <*> p2) <|> p3, if p2 fails we have to
            -- backtrack and start running p3. So we need to keep the input
            -- buffered until we know that the applicative cannot fail.
            SPartial n s -> return $ SContinue n (SeqParseL s)
            SContinue n s -> return $ SContinue n (SeqParseL s)
            SDone n b -> do
                -- XXX Use bimap if we make this a Step type
                -- fmap (bimap (SeqParseR (func b)) (func b)) initialR
                initR <- initialR
                return $ case initR of
                   IPartial sr -> SContinue n $ SeqParseR (func b) sr
                   IDone br -> SDone n (func b br)
                   IError err -> SError err
            SError err -> return $ SError err

    step (SeqParseR f st) a = fmap (bimap (SeqParseR f) f) (stepR st a)

    extract (SeqParseR f sR) = fmap (bimap (SeqParseR f) f) (extractR sR)
    extract (SeqParseL sL) = do
        -- XXX Use bimap here
        rL <- extractL sL
        case rL of
            FDone n bL -> do
                -- XXX Use bimap here if we use Step type in Initial
                iR <- initialR
                case iR of
                    IPartial sR -> do
                        fmap
                            (bimap (SeqParseR (func bL)) (func bL))
                            (extractR sR)
                    IDone bR -> return $ FDone n $ func bL bR
                    IError err -> return $ FError err
            FError err -> return $ FError err
            FContinue n s -> return $ FContinue n (SeqParseL s)

-------------------------------------------------------------------------------
-- Sequential applicative for backtracking folds
-------------------------------------------------------------------------------

-- XXX Create a newtype for nonfailing parsers and downgrade the parser to that
-- type before this operation and then upgrade.
--
-- We can do an inspection testing to reject unwanted constructors at compile
-- time.
--
-- We can use the compiler to automatically annotate accumulators, terminating
-- folds, non-failing parsers and failing parsers.

-- | Better performance 'splitWith' for non-failing parsers.
--
-- Does not work correctly for parsers that can fail.
--
-- ALL THE CAVEATS IN 'splitWith' APPLY HERE AS WELL.
--
{-# INLINE noErrorUnsafeSplitWith #-}
noErrorUnsafeSplitWith :: Monad m
    => (a -> b -> c) -> Parser x m a -> Parser x m b -> Parser x m c
noErrorUnsafeSplitWith func (Parser stepL initialL extractL)
               (Parser stepR initialR extractR) =
    Parser step initial extract

    where

    errMsg e = error $ "noErrorUnsafeSplitWith: unreachable: " ++ e

    initial = do
        resL <- initialL
        case resL of
            IPartial sl -> return $ IPartial $ SeqParseL sl
            IDone bl -> do
                resR <- initialR
                return $ bimap (SeqParseR (func bl)) (func bl) resR
            IError err -> errMsg err

    -- Note: For the composed parse to terminate, the left parser has to be
    -- a terminating parser returning a SDone at some point.
    step (SeqParseL st) a = do
        r <- stepL st a
        case r of
            -- Assume that the parser can never fail, therefore, we do not
            -- need to keep the input for backtracking.
            SPartial n s -> return $ SPartial n (SeqParseL s)
            SContinue n s -> return $ SContinue n (SeqParseL s)
            SDone n b -> do
                res <- initialR
                return
                    $ case res of
                          IPartial sr -> SPartial n $ SeqParseR (func b) sr
                          IDone br -> SDone n (func b br)
                          IError err -> errMsg err
            SError err -> errMsg err

    step (SeqParseR f st) a = fmap (bimap (SeqParseR f) f) (stepR st a)

    extract (SeqParseR f sR) = fmap (bimap (SeqParseR f) f) (extractR sR)

    extract (SeqParseL sL) = do
        rL <- extractL sL
        case rL of
            FDone n bL -> do
                iR <- initialR
                case iR of
                    IPartial sR -> do
                        rR <- extractR sR
                        return
                            $ bimapFinalOverrideCount
                                n (SeqParseR (func bL)) (func bL) rR
                    IDone bR -> return $ FDone n $ func bL bR
                    IError err -> errMsg err
            FError err -> errMsg err
            FContinue n s -> return $ FContinue n (SeqParseL s)

{-# ANN type SeqAState Fuse #-}
data SeqAState sl sr = SeqAL !sl | SeqAR !sr

-- This turns out to be slightly faster than splitWith

-- | Sequential parser application ignoring the output of the first parser.
-- Apply two parsers sequentially to an input stream.  The input is provided to
-- the first parser, when it is done the remaining input is provided to the
-- second parser. The output of the parser is the output of the second parser.
-- The operation fails if any of the parsers fail.
--
-- ALL THE CAVEATS IN 'splitWith' APPLY HERE AS WELL.
--
-- This implementation is strict in the second argument, therefore, the
-- following will fail:
--
-- >>> Stream.parse (Parser.split_ (Parser.satisfy (> 0)) undefined) $ Stream.fromList [1]
-- *** Exception: Prelude.undefined
-- ...
--
-- /Pre-release/
--
{-# INLINE split_ #-}
split_ :: Monad m => Parser x m a -> Parser x m b -> Parser x m b
split_ (Parser stepL initialL extractL) (Parser stepR initialR extractR) =
    Parser step initial extract

    where

    initial = do
        resL <- initialL
        case resL of
            IPartial sl -> return $ IPartial $ SeqAL sl
            IDone _ -> do
                resR <- initialR
                return $ first SeqAR resR
            IError err -> return $ IError err

    -- Note: For the composed parse to terminate, the left parser has to be
    -- a terminating parser returning a SDone at some point.
    step (SeqAL st) a = do
        -- Important: Do not use Applicative here. Applicative somehow caused
        -- the right action to run many times, not sure why though.
        resL <- stepL st a
        case resL of
            -- Note: this leads to buffering even if we are not in an
            -- Alternative composition.
            SPartial n s -> return $ SContinue n (SeqAL s)
            SContinue n s -> return $ SContinue n (SeqAL s)
            SDone n _ -> do
                initR <- initialR
                return $ case initR of
                    IPartial s -> SContinue n (SeqAR s)
                    IDone b -> SDone n b
                    IError err -> SError err
            SError err -> return $ SError err

    step (SeqAR st) a = first SeqAR <$> stepR st a

    extract (SeqAR sR) = fmap (first SeqAR) (extractR sR)
    extract (SeqAL sL) = do
        rL <- extractL sL
        case rL of
            FDone n _ -> do
                iR <- initialR
                -- XXX For initial we can have a bimap with leftover.
                case iR of
                    IPartial sR ->
                        fmap (bimapFinalOverrideCount n SeqAR id) (extractR sR)
                    IDone bR -> return $ FDone n bR
                    IError err -> return $ FError err
            FError err -> return $ FError err
            FContinue n s -> return $ FContinue n (SeqAL s)

-- | Better performance 'split_' for non-failing parsers.
--
-- Does not work correctly for parsers that can fail.
--
-- ALL THE CAVEATS IN 'splitWith' APPLY HERE AS WELL.
--
{-# INLINE noErrorUnsafeSplit_ #-}
noErrorUnsafeSplit_ :: Monad m => Parser x m a -> Parser x m b -> Parser x m b
noErrorUnsafeSplit_
    (Parser stepL initialL extractL) (Parser stepR initialR extractR) =
    Parser step initial extract

    where

    errMsg e = error $ "noErrorUnsafeSplit_: unreachable: " ++ e

    initial = do
        resL <- initialL
        case resL of
            IPartial sl -> return $ IPartial $ SeqAL sl
            IDone _ -> do
                resR <- initialR
                return $ first SeqAR resR
            IError err -> errMsg err

    -- Note: For the composed parse to terminate, the left parser has to be
    -- a terminating parser returning a SDone at some point.
    step (SeqAL st) a = do
        -- Important: Please do not use Applicative here. Applicative somehow
        -- caused the next action to run many times in the "tar" parsing code,
        -- not sure why though.
        resL <- stepL st a
        case resL of
            SPartial n s -> return $ SPartial n (SeqAL s)
            SContinue n s -> return $ SContinue n (SeqAL s)
            SDone n _ -> do
                initR <- initialR
                return $ case initR of
                    IPartial s -> SPartial n (SeqAR s)
                    IDone b -> SDone n b
                    IError err -> errMsg err
            SError err -> errMsg err

    step (SeqAR st) a = first SeqAR <$> stepR st a

    extract (SeqAR sR) = fmap (first SeqAR) (extractR sR)
    extract (SeqAL sL) = do
        rL <- extractL sL
        case rL of
            FDone n _ -> do
                iR <- initialR
                case iR of
                    IPartial sR -> do
                        fmap (bimapFinalOverrideCount n SeqAR id) (extractR sR)
                    IDone bR -> return $ FDone n bR
                    IError err -> errMsg err
            FError err -> errMsg err
            FContinue n s -> return $ FContinue n (SeqAL s)

-- | READ THE CAVEATS in 'splitWith' before using this instance.
--
-- >>> pure = Parser.fromPure
-- >>> (<*>) = Parser.splitWith id
-- >>> (*>) = Parser.split_
instance Monad m => Applicative (Parser a m) where
    {-# INLINE pure #-}
    pure = fromPure

    {-# INLINE (<*>) #-}
    (<*>) = splitWith id

    {-# INLINE (*>) #-}
    (*>) = split_

    {-# INLINE liftA2 #-}
    liftA2 f x = (<*>) (fmap f x)

-------------------------------------------------------------------------------
-- Sequential Alternative
-------------------------------------------------------------------------------

{-# ANN type AltParseState Fuse #-}
data AltParseState sl sr = AltParseL !Int !sl | AltParseR !sr

-- Note: this implementation of alt is fast because of stream fusion but has
-- quadratic time complexity, because each composition adds a new branch that
-- each subsequent alternative's input element has to go through, therefore, it
-- cannot scale to a large number of compositions

-- | Sequential alternative. The input is first passed to the first parser,
-- if it succeeds, the result is returned. However, if the first parser fails,
-- the parser driver backtracks and tries the same input on the second
-- (alternative) parser, returning the result if it succeeds.
--
-- This combinator delivers high performance by stream fusion but it comes with
-- some limitations. For those cases use the 'Alternative' instance of
-- 'Streamly.Data.ParserK.ParserK'.
--
-- CAVEAT 1: NO RECURSION. This function is strict in both arguments. As a
-- result, if a parser is defined recursively using this, it may cause an
-- infintie loop. The following example checks the strictness:
--
-- >> p = Parser.satisfy (> 0) `Parser.alt` undefined
-- >> Stream.parse p $ Stream.fromList [1..10]
-- *** Exception: Prelude.undefined
--
-- CAVEAT 2: QUADRATIC TIME COMPLEXITY. Static composition is fast due to
-- stream fusion, but it works well only for limited (e.g. up to 8)
-- compositions, use "Streamly.Data.ParserK" for larger compositions.
--
-- /Time Complexity:/ O(n^2) where n is the number of compositions.
--
-- /Pre-release/
--
{-# INLINE alt #-}
alt :: Monad m => Parser x m a -> Parser x m a -> Parser x m a
alt (Parser stepL initialL extractL) (Parser stepR initialR extractR) =
    Parser step initial extract

    where

    initial = do
        resL <- initialL
        case resL of
            IPartial sl -> return $ IPartial $ AltParseL 0 sl
            IDone bl -> return $ IDone bl
            IError _ -> do
                resR <- initialR
                return $ case resR of
                    IPartial sr -> IPartial $ AltParseR sr
                    IDone br -> IDone br
                    IError err -> IError err

    -- Once a parser yields at least one value it cannot fail.  This
    -- restriction helps us make backtracking more efficient, as we do not need
    -- to keep the consumed items buffered after a yield. Note that we do not
    -- enforce this and if a misbehaving parser does not honor this then we can
    -- get unexpected results. XXX Can we detect and flag this?
    step (AltParseL cnt st) a = do
        r <- stepL st a
        case r of
            SPartial n s -> return $ SPartial n (AltParseL 0 s)
            SContinue n s -> do
                assertM(cnt + n >= 0)
                return $ SContinue n (AltParseL (cnt + n) s)
            SDone n b -> return $ SDone n b
            SError _ -> do
                res <- initialR
                return
                    $ case res of
                          IPartial rR -> SContinue (negate cnt) (AltParseR rR)
                          IDone b -> SDone (negate cnt) b
                          IError err -> SError err

    step (AltParseR st) a = do
        r <- stepR st a
        return $ case r of
            SPartial n s -> SPartial n (AltParseR s)
            SContinue n s -> SContinue n (AltParseR s)
            SDone n b -> SDone n b
            SError err -> SError err

    extract (AltParseR sR) = fmap (first AltParseR) (extractR sR)

    extract (AltParseL cnt sL) = do
        rL <- extractL sL
        case rL of
            FDone n b -> return $ FDone n b
            FError _ -> do
                res <- initialR
                return
                    $ case res of
                          IPartial rR -> FContinue (- cnt) (AltParseR rR)
                          IDone b -> FDone (- cnt) b
                          IError err -> FError err
            FContinue n s -> do
                assertM(n == (- cnt))
                return $ FContinue n (AltParseL 0 s)

{-# ANN type Fused3 Fuse #-}
data Fused3 a b c = Fused3 !a !b !c

-- | See documentation of 'Streamly.Internal.Data.Parser.many'.
--
-- /Pre-release/
--
{-# INLINE splitMany #-}
splitMany :: Monad m => Parser a m b -> Fold m b c -> Parser a m c
splitMany (Parser step1 initial1 extract1) (Fold fstep finitial _ ffinal) =
    Parser step initial extract

    where

    -- Caution! There is mutual recursion here, inlining the right functions is
    -- important.

    handleCollect partial done fres =
        case fres of
            FL.Partial fs -> do
                pres <- initial1
                case pres of
                    IPartial ps -> return $ partial $ Fused3 ps 0 fs
                    IDone pb ->
                        runCollectorWith (handleCollect partial done) fs pb
                    IError _ -> done <$> ffinal fs
            FL.Done fb -> return $ done fb

    runCollectorWith cont fs pb = fstep fs pb >>= cont

    -- See notes in Fold.many for the reason why the parser must be initialized
    -- right away instead of on first input.
    initial = finitial >>= handleCollect IPartial IDone

    {-# INLINE step #-}
    step (Fused3 st cnt fs) a = do
        r <- step1 st a
        case r of
            SPartial n s -> do
                assertM(cnt + n >= 0)
                return $ SContinue n (Fused3 s (cnt + n) fs)
            SContinue n s -> do
                assertM(cnt + n >= 0)
                return $ SContinue n (Fused3 s (cnt + n) fs)
            SDone n b -> do
                assertM(cnt + n >= 0)
                fstep fs b >>= handleCollect (SPartial n) (SDone n)
            SError _ -> do
                xs <- ffinal fs
                -- XXX review, need a test for this
                return $ SDone (- cnt) xs

    extract (Fused3 _ 0 fs) = fmap (FDone 0) (ffinal fs)
    extract (Fused3 s cnt fs) = do
        r <- extract1 s
        case r of
            FError _ -> fmap (FDone (- cnt)) (ffinal fs)
            FDone n b -> do
                assertM((- n) <= cnt)
                fs1 <- fstep fs b
                case fs1 of
                    FL.Partial s1 -> fmap (FDone n) (ffinal s1)
                    FL.Done b1 -> return (FDone n b1)
            FContinue n s1 -> do
                assertM((- n) == cnt)
                return (FContinue n (Fused3 s1 0 fs))

-- | Like splitMany, but inner fold emits an output at the end even if no input
-- is received.
--
-- /Internal/
--
{-# INLINE splitManyPost #-}
splitManyPost :: Monad m =>  Parser a m b -> Fold m b c -> Parser a m c
splitManyPost (Parser step1 initial1 extract1) (Fold fstep finitial _ ffinal) =
    Parser step initial extract

    where

    -- Caution! There is mutual recursion here, inlining the right functions is
    -- important.

    handleCollect partial done fres =
        case fres of
            FL.Partial fs -> do
                pres <- initial1
                case pres of
                    IPartial ps -> return $ partial $ Fused3 ps 0 fs
                    IDone pb ->
                        runCollectorWith (handleCollect partial done) fs pb
                    IError _ -> done <$> ffinal fs
            FL.Done fb -> return $ done fb

    runCollectorWith cont fs pb = fstep fs pb >>= cont

    initial = finitial >>= handleCollect IPartial IDone

    {-# INLINE step #-}
    step (Fused3 st cnt fs) a = do
        r <- step1 st a
        case r of
            SPartial n s -> do
                assertM(cnt + n >= 0)
                return $ SContinue n (Fused3 s (cnt + n) fs)
            SContinue n s -> do
                assertM(cnt + n >= 0)
                return $ SContinue n (Fused3 s (cnt + n) fs)
            SDone n b -> do
                assertM(cnt + n >= 0)
                fstep fs b >>= handleCollect (SPartial n) (SDone n)
            SError _ -> do
                xs <- ffinal fs
                return $ SDone (- cnt) xs

    extract (Fused3 s cnt fs) = do
        r <- extract1 s
        case r of
            FError _ -> fmap (FDone (- cnt)) (ffinal fs)
            FDone n b -> do
                assertM((- n) <= cnt)
                fs1 <- fstep fs b
                case fs1 of
                    FL.Partial s1 -> fmap (FDone n) (ffinal s1)
                    FL.Done b1 -> return (FDone n b1)
            FContinue n s1 -> do
                assertM((- n) == cnt)
                return (FContinue n (Fused3 s1 0 fs))

-- | See documentation of 'Streamly.Internal.Data.Parser.some'.
--
-- /Pre-release/
--
{-# INLINE splitSome #-}
splitSome :: Monad m => Parser a m b -> Fold m b c -> Parser a m c
splitSome (Parser step1 initial1 extract1) (Fold fstep finitial _ ffinal) =
    Parser step initial extract

    where

    -- Caution! There is mutual recursion here, inlining the right functions is
    -- important.

    handleCollect partial done fres =
        case fres of
            FL.Partial fs -> do
                pres <- initial1
                case pres of
                    IPartial ps -> return $ partial $ Fused3 ps 0 $ Right fs
                    IDone pb ->
                        runCollectorWith (handleCollect partial done) fs pb
                    IError _ -> done <$> ffinal fs
            FL.Done fb -> return $ done fb

    runCollectorWith cont fs pb = fstep fs pb >>= cont

    initial = do
        fres <- finitial
        case fres of
            FL.Partial fs -> do
                pres <- initial1
                case pres of
                    IPartial ps -> return $ IPartial $ Fused3 ps 0 $ Left fs
                    IDone pb ->
                        runCollectorWith (handleCollect IPartial IDone) fs pb
                    IError err -> return $ IError err
            FL.Done _ ->
                return
                    $ IError
                    $ "splitSome: The collecting fold terminated without"
                          ++ " consuming any elements."

    {-# INLINE step #-}
    step (Fused3 st cnt (Left fs)) a = do
        r <- step1 st a
        -- In the Left state, count is used only for the assert
        case r of
            SPartial n s -> do
                assertM(cnt + n >= 0)
                return $ SContinue n (Fused3 s (cnt + n) (Left fs))
            SContinue n s -> do
                assertM(cnt + n >= 0)
                return $ SContinue n (Fused3 s (cnt + n) (Left fs))
            SDone n b -> do
                assertM(cnt + n >= 0)
                fstep fs b >>= handleCollect (SPartial n) (SDone n)
            SError err -> return $ SError err
    step (Fused3 st cnt (Right fs)) a = do
        r <- step1 st a
        case r of
            SPartial n s -> do
                assertM(cnt + n >= 0)
                return $ SPartial n (Fused3 s (cnt + n) (Right fs))
            SContinue n s -> do
                assertM(cnt + n >= 0)
                return $ SContinue n (Fused3 s (cnt + n) (Right fs))
            SDone n b -> do
                assertM(cnt + n >= 0)
                fstep fs b >>= handleCollect (SPartial n) (SDone n)
            SError _ -> SDone (- cnt) <$> ffinal fs

    extract (Fused3 s cnt (Left fs)) = do
        r <- extract1 s
        case r of
            FError err -> return (FError err)
            FDone n b -> do
                assertM((- n) <= cnt)
                fs1 <- fstep fs b
                case fs1 of
                    FL.Partial s1 -> fmap (FDone n) (ffinal s1)
                    FL.Done b1 -> return (FDone n b1)
            FContinue n s1 -> do
                assertM((- n) == cnt)
                return (FContinue n (Fused3 s1 0 (Left fs)))
    extract (Fused3 s cnt (Right fs)) = do
        r <- extract1 s
        case r of
            FError _ -> fmap (FDone (- cnt)) (ffinal fs)
            FDone n b -> do
                assertM((- n) <= cnt)
                fs1 <- fstep fs b
                case fs1 of
                    FL.Partial s1 -> fmap (FDone n) (ffinal s1)
                    FL.Done b1 -> return (FDone n b1)
            FContinue n s1 -> do
                assertM((- n) == cnt)
                return (FContinue n (Fused3 s1 0 (Right fs)))

-- | A parser that always fails with an error message without consuming
-- any input.
--
{-# INLINE_NORMAL die #-}
die :: Monad m => String -> Parser a m b
die err = Parser undefined (pure (IError err)) undefined

-- | A parser that always fails with an effectful error message and without
-- consuming any input.
--
-- /Pre-release/
--
{-# INLINE dieM #-}
dieM :: Monad m => m String -> Parser a m b
dieM err = Parser undefined (IError <$> err) undefined

-- Note: The default implementations of "some" and "many" loop infinitely
-- because of the strict pattern match on both the arguments in applicative and
-- alternative. With the direct style parser type we cannot use the mutually
-- recursive definitions of "some" and "many".
--
-- Note: With the direct style parser type, the list in "some" and "many" is
-- accumulated strictly, it cannot be consumed lazily.

-- | READ THE CAVEATS in 'alt' before using this instance.
--
-- >>> empty = Parser.die "empty"
-- >>> (<|>) = Parser.alt
-- >>> many = flip Parser.many Fold.toList
-- >>> some = flip Parser.some Fold.toList
instance Monad m => Alternative (Parser a m) where
    {-# INLINE empty #-}
    empty = die "empty"

    {-# INLINE (<|>) #-}
    (<|>) = alt

    {-# INLINE many #-}
    many = flip splitMany toList

    {-# INLINE some #-}
    some = flip splitSome toList

{-# ANN type ConcatParseState Fuse #-}
data ConcatParseState sl m a b =
      ConcatParseL !sl
    | forall s. ConcatParseR (s -> a -> m (Step s b)) s (s -> m (Final s b))

-- XXX Does it fuse completely? Check and update, it cannot fuse the
-- dynamically generated parser.

-- | Map a 'Parser' returning function on the result of a 'Parser'.
--
-- ALL THE CAVEATS IN 'splitWith' APPLY HERE AS WELL.
--
-- /Pre-release/
--
{-# INLINE concatMap #-}
concatMap :: Monad m =>
    (b -> Parser a m c) -> Parser a m b -> Parser a m c
concatMap func (Parser stepL initialL extractL) = Parser step initial extract

    where

    {-# INLINE initializeR #-}
    initializeR (Parser stepR initialR extractR) = do
        resR <- initialR
        return $ case resR of
            IPartial sr -> IPartial $ ConcatParseR stepR sr extractR
            IDone br -> IDone br
            IError err -> IError err

    initial = do
        res <- initialL
        case res of
            IPartial s -> return $ IPartial $ ConcatParseL s
            IDone b -> initializeR (func b)
            IError err -> return $ IError err

    {-# INLINE initializeRL #-}
    initializeRL n (Parser stepR initialR extractR) = do
        resR <- initialR
        return $ case resR of
            IPartial sr -> SContinue n $ ConcatParseR stepR sr extractR
            IDone br -> SDone n br
            IError err -> SError err

    step (ConcatParseL st) a = do
        r <- stepL st a
        case r of
            SPartial n s -> return $ SContinue n (ConcatParseL s)
            SContinue n s -> return $ SContinue n (ConcatParseL s)
            SDone n b -> initializeRL n (func b)
            SError err -> return $ SError err

    step (ConcatParseR stepR st extractR) a = do
        r <- stepR st a
        return $ case r of
            SPartial n s -> SPartial n $ ConcatParseR stepR s extractR
            SContinue n s -> SContinue n $ ConcatParseR stepR s extractR
            SDone n b -> SDone n b
            SError err -> SError err

    {-# INLINE extractP #-}
    extractP n (Parser stepR initialR extractR) = do
        res <- initialR
        case res of
            IPartial s ->
                fmap
                    (first (\s1 -> ConcatParseR stepR s1 extractR))
                    (extractR s)
            IDone b -> return (FDone n b)
            IError err -> return $ FError err

    extract (ConcatParseR stepR s extractR) =
        fmap (first (\s1 -> ConcatParseR stepR s1 extractR)) (extractR s)
    extract (ConcatParseL sL) = do
        rL <- extractL sL
        case rL of
            FError err -> return $ FError err
            FDone n b -> extractP n $ func b
            FContinue n s -> return $ FContinue n (ConcatParseL s)

-- | Better performance 'concatMap' for non-failing parsers.
--
-- Does not work correctly for parsers that can fail.
--
-- ALL THE CAVEATS IN 'splitWith' APPLY HERE AS WELL.
--
{-# INLINE noErrorUnsafeConcatMap #-}
noErrorUnsafeConcatMap :: Monad m =>
    (b -> Parser a m c) -> Parser a m b -> Parser a m c
noErrorUnsafeConcatMap func (Parser stepL initialL extractL) =
    Parser step initial extract

    where

    {-# INLINE initializeR #-}
    initializeR (Parser stepR initialR extractR) = do
        resR <- initialR
        return $ case resR of
            IPartial sr -> IPartial $ ConcatParseR stepR sr extractR
            IDone br -> IDone br
            IError err -> IError err

    initial = do
        res <- initialL
        case res of
            IPartial s -> return $ IPartial $ ConcatParseL s
            IDone b -> initializeR (func b)
            IError err -> return $ IError err

    {-# INLINE initializeRL #-}
    initializeRL n (Parser stepR initialR extractR) = do
        resR <- initialR
        return $ case resR of
            IPartial sr -> SPartial n $ ConcatParseR stepR sr extractR
            IDone br -> SDone n br
            IError err -> SError err

    step (ConcatParseL st) a = do
        r <- stepL st a
        case r of
            SPartial n s -> return $ SPartial n (ConcatParseL s)
            SContinue n s -> return $ SContinue n (ConcatParseL s)
            SDone n b -> initializeRL n (func b)
            SError err -> return $ SError err

    step (ConcatParseR stepR st extractR) a = do
        r <- stepR st a
        return $ case r of
            SPartial n s -> SPartial n $ ConcatParseR stepR s extractR
            SContinue n s -> SContinue n $ ConcatParseR stepR s extractR
            SDone n b -> SDone n b
            SError err -> SError err

    {-# INLINE extractP #-}
    extractP n (Parser stepR initialR extractR) = do
        res <- initialR
        case res of
            IPartial s ->
                fmap
                    (first (\s1 -> ConcatParseR stepR s1 extractR))
                    (extractR s)
            IDone b -> return (FDone n b)
            IError err -> return $ FError err

    extract (ConcatParseR stepR s extractR) =
        fmap (first (\s1 -> ConcatParseR stepR s1 extractR)) (extractR s)
    extract (ConcatParseL sL) = do
        rL <- extractL sL
        case rL of
            FError err -> return $ FError err
            FDone n b -> extractP n $ func b
            FContinue n s -> return $ FContinue n (ConcatParseL s)

-- Note: The monad instance has quadratic performance complexity. It works fine
-- for small number of compositions but for a scalable implementation we need a
-- CPS version.

-- | READ THE CAVEATS in 'concatMap' before using this instance.
--
-- >>> (>>=) = flip Parser.concatMap
--
instance Monad m => Monad (Parser a m) where
    {-# INLINE return #-}
    return = pure

    {-# INLINE (>>=) #-}
    (>>=) = flip concatMap

    {-# INLINE (>>) #-}
    (>>) = (*>)

-- | >>> fail = Parser.die
instance Monad m => Fail.MonadFail (Parser a m) where
    {-# INLINE fail #-}
    fail = die

{-
-- | See documentation of 'Streamly.Internal.Data.Parser.ParserK.Type.Parser'.
--
instance Monad m => MonadPlus (Parser a m) where
    {-# INLINE mzero #-}
    mzero = die "mzero"

    {-# INLINE mplus #-}
    mplus = alt
-}

-- | >>> liftIO = Parser.fromEffect . liftIO
instance (MonadIO m) => MonadIO (Parser a m) where
    {-# INLINE liftIO #-}
    liftIO = fromEffect . liftIO

------------------------------------------------------------------------------
-- Mapping on input
------------------------------------------------------------------------------

-- | @lmap f parser@ maps the function @f@ on the input of the parser.
--
-- >>> Stream.parse (Parser.lmap (\x -> x * x) (Parser.fromFold Fold.sum)) (Stream.enumerateFromTo 1 100)
-- Right 338350
--
-- > lmap = Parser.lmapM return
--
{-# INLINE lmap #-}
lmap :: (a -> b) -> Parser b m r -> Parser a m r
lmap f (Parser step begin done) = Parser step1 begin done

    where

    step1 x a = step x (f a)

-- | @lmapM f parser@ maps the monadic function @f@ on the input of the parser.
--
{-# INLINE lmapM #-}
lmapM :: Monad m => (a -> m b) -> Parser b m r -> Parser a m r
lmapM f (Parser step begin done) = Parser step1 begin done

    where

    step1 x a = f a >>= step x

-- | Include only those elements that pass a predicate.
--
-- >>> Stream.parse (Parser.filter (> 5) (Parser.fromFold Fold.sum)) $ Stream.fromList [1..10]
-- Right 40
--
{-# INLINE filter #-}
filter :: Monad m => (a -> Bool) -> Parser a m b -> Parser a m b
filter f (Parser step initial extract) = Parser step1 initial extract

    where

    step1 x a = if f a then step x a else return $ SPartial 1 x

-- XXX move this to ParserD.Transformer

-- | Modify the environment of the underlying ReaderT monad.
{-# INLINE localReaderT #-}
localReaderT ::
    (r -> r) -> Parser a (ReaderT r m) b -> Parser a (ReaderT r m) b
localReaderT f (Parser step initial extract) =
    Parser
        ((local f .) . step)
        (local f initial)
        (local f . extract)
